<template>
    <div class="image-upload">
        <van-uploader v-model="fileList" :max-count="maxCount" :max-size="maxSize" multiple
            :after-read="handleAfterRead" :before-delete="handleBeforeDelete" @oversize="handleOversize"
            @delete="handleDelete">
            <div class="upload-button">
                <van-icon name="photograph" size="24" />
                <span>Add Images</span>
                <div class="upload-hint">{{ fileList.length }}/{{ maxCount }}</div>
            </div>
        </van-uploader>

        <!-- 图片预览和编辑 -->
        <div class="image-preview-list" v-if="fileList.length > 0">
            <div v-for="(file, index) in fileList" :key="index" class="image-preview-item">
                <van-image :src="file.url || file.content" width="80" height="80" fit="cover"
                    @click="previewImage(index)" />
                <div class="image-actions">
                    <van-icon name="edit" @click="editImage(index)" />
                    <van-icon name="delete-o" @click="deleteImage(index)" />
                </div>
                <div class="image-info">
                    <div class="image-name">{{ file.name || `Image ${index + 1}` }}</div>
                    <div class="image-size">{{ formatFileSize(file.size) }}</div>
                </div>
            </div>
        </div>

        <!-- 图片编辑弹窗 -->
        <van-popup v-model:show="showEditPopup" position="center" round>
            <div class="image-edit-popup" v-if="editingImage">
                <div class="popup-header">
                    <h3>Edit Image</h3>
                    <van-icon name="cross" @click="showEditPopup = false" />
                </div>
                <div class="popup-content">
                    <van-image :src="editingImage.url || editingImage.content" width="200" height="200" fit="cover" />
                    <van-field v-model="editingImage.alt" label="Alt Text" placeholder="Describe this image..."
                        maxlength="100" show-word-limit />
                    <van-field v-model="editingImage.caption" label="Caption" placeholder="Add a caption..."
                        maxlength="200" show-word-limit />
                </div>
                <div class="popup-actions">
                    <van-button block @click="showEditPopup = false">Cancel</van-button>
                    <van-button type="primary" block @click="saveImageEdit">Save</van-button>
                </div>
            </div>
        </van-popup>

        <!-- 图片预览 -->
        <van-image-preview v-model:show="showPreview" :images="previewImages" :start-position="previewIndex"
            closeable />

        <!-- 上传进度 -->
        <van-overlay :show="uploading">
            <div class="upload-progress">
                <van-loading size="24px" vertical>
                    Uploading images...
                </van-loading>
                <div class="progress-info">
                    {{ uploadedCount }}/{{ totalUploadCount }} uploaded
                </div>
            </div>
        </van-overlay>
    </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { showToast, showConfirmDialog } from 'vant'

interface ImageFile {
    file?: File
    url?: string
    content?: string
    name?: string
    size?: number
    alt?: string
    caption?: string
}

interface Props {
    modelValue: ImageFile[]
    maxCount?: number
    maxSize?: number // in bytes
    accept?: string
}

interface Emits {
    (e: 'update:modelValue', files: ImageFile[]): void
    (e: 'upload', files: ImageFile[]): void
}

const props = withDefaults(defineProps<Props>(), {
    maxCount: 9,
    maxSize: 5 * 1024 * 1024, // 5MB
    accept: 'image/*'
})

const emit = defineEmits<Emits>()

// 响应式数据
const fileList = ref<ImageFile[]>([...props.modelValue])
const showEditPopup = ref(false)
const showPreview = ref(false)
const editingImage = ref<ImageFile | null>(null)
const editingIndex = ref(-1)
const previewIndex = ref(0)
const uploading = ref(false)
const uploadedCount = ref(0)
const totalUploadCount = ref(0)

// 计算属性
const previewImages = computed(() =>
    fileList.value.map(file => file.url || file.content || '')
)

// 方法
const handleAfterRead = async (file: any) => {
    if (Array.isArray(file)) {
        // 多个文件
        for (const f of file) {
            await processFile(f)
        }
    } else {
        // 单个文件
        await processFile(file)
    }

    emit('update:modelValue', fileList.value)
    emit('upload', fileList.value)
}

const processFile = async (file: any) => {
    // 压缩图片
    const compressedFile = await compressImage(file.file)

    const imageFile: ImageFile = {
        file: compressedFile,
        url: file.content,
        content: file.content,
        name: file.file?.name || 'image',
        size: compressedFile.size,
        alt: '',
        caption: ''
    }

    fileList.value.push(imageFile)
}

const compressImage = async (file: File): Promise<File> => {
    return new Promise((resolve) => {
        const canvas = document.createElement('canvas')
        const ctx = canvas.getContext('2d')
        const img = new Image()

        img.onload = () => {
            // 计算压缩后的尺寸
            const maxWidth = 1200
            const maxHeight = 1200
            let { width, height } = img

            if (width > height) {
                if (width > maxWidth) {
                    height = (height * maxWidth) / width
                    width = maxWidth
                }
            } else {
                if (height > maxHeight) {
                    width = (width * maxHeight) / height
                    height = maxHeight
                }
            }

            canvas.width = width
            canvas.height = height

            // 绘制压缩后的图片
            ctx?.drawImage(img, 0, 0, width, height)

            canvas.toBlob(
                (blob) => {
                    if (blob) {
                        const compressedFile = new File([blob], file.name, {
                            type: 'image/jpeg',
                            lastModified: Date.now()
                        })
                        resolve(compressedFile)
                    } else {
                        resolve(file)
                    }
                },
                'image/jpeg',
                0.8 // 压缩质量
            )
        }

        img.src = URL.createObjectURL(file)
    })
}

const handleBeforeDelete = async () => {
    try {
        await showConfirmDialog({
            title: 'Delete Image',
            message: 'Are you sure you want to delete this image?'
        })
        return true
    } catch {
        return false
    }
}

const handleDelete = (file: any, detail: any) => {
    fileList.value.splice(detail.index, 1)
    emit('update:modelValue', fileList.value)
}

const handleOversize = () => {
    showToast(`Image size cannot exceed ${formatFileSize(props.maxSize)}`)
}

const deleteImage = async (index: number) => {
    try {
        await showConfirmDialog({
            title: 'Delete Image',
            message: 'Are you sure you want to delete this image?'
        })

        fileList.value.splice(index, 1)
        emit('update:modelValue', fileList.value)
        showToast('Image deleted')
    } catch {
        // 用户取消
    }
}

const editImage = (index: number) => {
    editingIndex.value = index
    editingImage.value = { ...fileList.value[index] }
    showEditPopup.value = true
}

const saveImageEdit = () => {
    if (editingImage.value && editingIndex.value >= 0) {
        fileList.value[editingIndex.value] = { ...editingImage.value }
        emit('update:modelValue', fileList.value)
        showEditPopup.value = false
        showToast('Image updated')
    }
}

const previewImage = (index: number) => {
    previewIndex.value = index
    showPreview.value = true
}

const formatFileSize = (bytes?: number): string => {
    if (!bytes) return '0 B'

    const k = 1024
    const sizes = ['B', 'KB', 'MB', 'GB']
    const i = Math.floor(Math.log(bytes) / Math.log(k))

    return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]
}

// 模拟上传进度
const simulateUpload = async () => {
    uploading.value = true
    uploadedCount.value = 0
    totalUploadCount.value = fileList.value.length

    for (let i = 0; i < fileList.value.length; i++) {
        // 模拟上传延迟
        await new Promise(resolve => setTimeout(resolve, 500))
        uploadedCount.value++
    }

    uploading.value = false
    showToast('All images uploaded successfully!')
}

// 暴露方法给父组件
defineExpose({
    simulateUpload
})
</script>

<style lang="scss" scoped>
.image-upload {
    .upload-button {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        padding: 20px;
        border: 2px dashed #c8c9cc;
        border-radius: 8px;
        background: #f7f8fa;
        color: #646566;
        cursor: pointer;
        transition: all 0.3s;

        &:hover {
            border-color: #1989fa;
            color: #1989fa;
        }

        .van-icon {
            margin-bottom: 8px;
        }

        span {
            font-size: 14px;
            margin-bottom: 4px;
        }

        .upload-hint {
            font-size: 12px;
            color: #969799;
        }
    }

    .image-preview-list {
        margin-top: 16px;
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
        gap: 12px;

        .image-preview-item {
            position: relative;
            background: white;
            border-radius: 8px;
            padding: 8px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);

            .van-image {
                border-radius: 4px;
                cursor: pointer;
            }

            .image-actions {
                position: absolute;
                top: 4px;
                right: 4px;
                display: flex;
                gap: 4px;

                .van-icon {
                    width: 24px;
                    height: 24px;
                    background: rgba(0, 0, 0, 0.6);
                    color: white;
                    border-radius: 50%;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    cursor: pointer;
                    font-size: 12px;

                    &:hover {
                        background: rgba(0, 0, 0, 0.8);
                    }
                }
            }

            .image-info {
                margin-top: 8px;

                .image-name {
                    font-size: 12px;
                    color: #323233;
                    font-weight: 500;
                    margin-bottom: 2px;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                }

                .image-size {
                    font-size: 11px;
                    color: #969799;
                }
            }
        }
    }
}

.image-edit-popup {
    padding: 20px;
    width: 300px;

    .popup-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 20px;

        h3 {
            font-size: 18px;
            color: #323233;
            margin: 0;
            font-weight: 600;
        }

        .van-icon {
            color: #969799;
            cursor: pointer;
        }
    }

    .popup-content {
        margin-bottom: 20px;

        .van-image {
            margin-bottom: 16px;
            border-radius: 8px;
        }

        .van-field {
            margin-bottom: 12px;
        }
    }

    .popup-actions {
        display: flex;
        gap: 12px;
    }
}

.upload-progress {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100vh;
    color: white;

    .progress-info {
        margin-top: 16px;
        font-size: 14px;
    }
}
</style>